#pragma once

#include "RenderingData.h"
#include "RenderingSettings.h"

namespace mmath
{
	struct FrustumPersp;
}

namespace mgfx
{
	struct RenderingData;
	struct RenderingSettings;
	struct MeshDesc;
	class MeshInstance;
	class DirectionalLight;
	class PointLight;
	class SpotLight;
	class ParticleSystem;
	class GfxObject;

	class Renderer;

	struct PointLightDesc;
	struct SpotLightDesc;
	struct ParticleSystemDesc;

	class RenderingSystem
	{
	public:
		RenderingSystem();
		~RenderingSystem();

		void update(float dt);

		MeshInstance * createMeshInstance(const std::string & filename, uint id = INCORRECT_OBJ_ID);
		MeshInstance * createMeshInstance(const MeshDesc & desc, uint id = INCORRECT_OBJ_ID);

		MeshInstance * createMeshInstanceCopy(const MeshInstance & src);

		DirectionalLight * getMainLight();

		PointLight * createPointLight(const PointLightDesc & desc, uint id = INCORRECT_OBJ_ID);
		PointLight * createPointLightCopy(const PointLight & src);

		SpotLight * createSpotLight(const SpotLightDesc & desc, uint id = INCORRECT_OBJ_ID);
		SpotLight * createSpotLightCopy(const SpotLight & src);

		ParticleSystem * createParticleSystem(const ParticleSystemDesc & desc, uint id = INCORRECT_OBJ_ID);

		void setViewMatrix(const XMFLOAT4X4 & view);
		void setProjMatrix(const XMFLOAT4X4 & proj);
		void setEyePosition(const XMFLOAT3 & eyePos);
		void setViewFrustum(const mmath::FrustumPersp & frustum);

		RenderingSettings Settings;
		RenderingData Data;

		GfxObject & findGfxObject(uint id);
		void removeGfxObject(GfxObject & obj);

		

	private:
		void addToGfxObjectMap(GfxObject & rb, uint id = INCORRECT_OBJ_ID);
		void updateGfxObjectMapEntry(GfxObject & rb);
		void removeGfxObjectMapEntry(GfxObject & rb);

		std::map<uint, GfxObject*> mGfxObjects;
		static const uint INCORRECT_OBJ_ID = 0;
		uint mNextID;
		
	};
}